/*
 * Created on 20/10/2012 - 12:40 PM
 */
package sembr.vtk.data.input;

import vtk.*;

/**
 *
 * @author adriano
 */

public class PCF2 extends SourceBase
{
    private vtkCylinderSource cylinder;
    private vtkAppendPolyData tubes;
    private vtkAppendPolyData device;
                    
    public PCF2(double[] center, double radius, double height, int resolution)
    {
        cylinder = new vtkCylinderSource();
        cylinder.SetCenter(center);
        cylinder.SetRadius(radius);
        cylinder.SetHeight(height);
        cylinder.SetResolution(resolution); 
        cylinder.CappingOn();
        cylinder.Update();
        setTubes();
        setTubesDieletric(1.0);
        setCylinderDieletric(12.0);
        appendTubesWithCylinder();
        setDeviceScalar();      
    }
    
    private void setTubes()
    {        
        double xShift;  
        double zShift;
        vtkCylinderSource currentCylinder;
        vtkCylinderSource xMirrorCurrentCylinder;       
        vtkCylinderSource yMirrorCurrentCylinder;
        vtkCylinderSource xyMirrorCurrentCylinder;
        // seventeen tubes fill the cylinder diameter queued side by side
        double tubesDiameter = (cylinder.GetRadius() * 2) / 17;
        double[] origin = cylinder.GetCenter();
                
        tubes = new vtkAppendPolyData();
        int i;
        // for central tubes
        for (i = 2; i <= 6; i = i + 2)
        {            
            // determine center
            xShift = origin[0] + i * tubesDiameter;
            
            currentCylinder = new vtkCylinderSource();
            xMirrorCurrentCylinder = new vtkCylinderSource();
                        
            currentCylinder.SetCenter(xShift, origin[1], origin[2]);
            currentCylinder.SetRadius(tubesDiameter / 2);
            currentCylinder.SetHeight(cylinder.GetHeight());
            currentCylinder.SetResolution(cylinder.GetResolution());
            
            xMirrorCurrentCylinder.SetCenter(-xShift, origin[1], origin[2]);
            xMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
                        
            currentCylinder.CappingOn();
            xMirrorCurrentCylinder.CappingOn();
            
            tubes.AddInput(currentCylinder.GetOutput());
            tubes.AddInput(xMirrorCurrentCylinder.GetOutput());
        }
        
        // middle tubes displacement in z coodinate
        zShift = origin[2] + 2 * tubesDiameter;
        
        for (i = 1; i <= 5; i = i + 2) 
        {
            xShift = origin[0] + i * tubesDiameter;
            
            currentCylinder = new vtkCylinderSource();
            xMirrorCurrentCylinder = new vtkCylinderSource();
            yMirrorCurrentCylinder = new vtkCylinderSource();
            xyMirrorCurrentCylinder = new vtkCylinderSource();
                        
            currentCylinder.SetCenter(xShift, origin[1], zShift);
            currentCylinder.SetRadius(tubesDiameter / 2);
            currentCylinder.SetHeight(cylinder.GetHeight());
            currentCylinder.SetResolution(cylinder.GetResolution());
            
            xMirrorCurrentCylinder.SetCenter(-xShift, origin[1], zShift);
            xMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            yMirrorCurrentCylinder.SetCenter(xShift, origin[1], -zShift);
            yMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            yMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            yMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            xyMirrorCurrentCylinder.SetCenter(-xShift, origin[1], -zShift);
            xyMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xyMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xyMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            currentCylinder.CappingOn();
            xMirrorCurrentCylinder.CappingOn();
            yMirrorCurrentCylinder.CappingOn();
            xyMirrorCurrentCylinder.CappingOn();
            
            tubes.AddInput(currentCylinder.GetOutput());
            tubes.AddInput(xMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(yMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(xyMirrorCurrentCylinder.GetOutput());
        }
      
        // second middle tubes displacement in y coodinate 
        zShift = origin[2] + 4 * tubesDiameter;
        
        for (i = 0; i <= 4; i = i + 2)
        {
            xShift = origin[0] + i * tubesDiameter;
            
            currentCylinder = new vtkCylinderSource();
            xMirrorCurrentCylinder = new vtkCylinderSource();
            yMirrorCurrentCylinder = new vtkCylinderSource();
            xyMirrorCurrentCylinder = new vtkCylinderSource();
                        
            currentCylinder.SetCenter(xShift, origin[1], zShift);
            currentCylinder.SetRadius(tubesDiameter / 2);
            currentCylinder.SetHeight(cylinder.GetHeight());
            currentCylinder.SetResolution(cylinder.GetResolution());
            
            xMirrorCurrentCylinder.SetCenter(-xShift, origin[1], zShift);
            xMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            yMirrorCurrentCylinder.SetCenter(xShift, origin[1], -zShift);
            yMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            yMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            yMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            xyMirrorCurrentCylinder.SetCenter(-xShift, origin[1], -zShift);
            xyMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xyMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xyMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
//                                    
            currentCylinder.CappingOn();
            xMirrorCurrentCylinder.CappingOn();
            yMirrorCurrentCylinder.CappingOn();
            xyMirrorCurrentCylinder.CappingOn();
            
            tubes.AddInput(currentCylinder.GetOutput());
            tubes.AddInput(xMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(yMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(xyMirrorCurrentCylinder.GetOutput());            
        }
        
        // second middle tubes displacement in y coodinate 
        zShift = origin[2] + 6 * tubesDiameter;
        
        for (i = 1; i <= 3; i = i + 2)
        {
            xShift = origin[0] + i * tubesDiameter;            
            
            currentCylinder = new vtkCylinderSource();
            xMirrorCurrentCylinder = new vtkCylinderSource();
            yMirrorCurrentCylinder = new vtkCylinderSource();
            xyMirrorCurrentCylinder = new vtkCylinderSource();
            
            currentCylinder.SetCenter(xShift, origin[1], zShift);
            currentCylinder.SetRadius(tubesDiameter / 2);
            currentCylinder.SetHeight(cylinder.GetHeight());
            currentCylinder.SetResolution(cylinder.GetResolution());
            
            xMirrorCurrentCylinder.SetCenter(-xShift, origin[1], zShift);
            xMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            yMirrorCurrentCylinder.SetCenter(xShift, origin[1], -zShift);
            yMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            yMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            yMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
            
            xyMirrorCurrentCylinder.SetCenter(-xShift, origin[1], -zShift);
            xyMirrorCurrentCylinder.SetRadius(tubesDiameter / 2);
            xyMirrorCurrentCylinder.SetHeight(cylinder.GetHeight());
            xyMirrorCurrentCylinder.SetResolution(cylinder.GetResolution());
//            
            currentCylinder.CappingOn();
            xMirrorCurrentCylinder.CappingOn();
            yMirrorCurrentCylinder.CappingOn();
            xyMirrorCurrentCylinder.CappingOn();
//            
            tubes.AddInput(currentCylinder.GetOutput());
            tubes.AddInput(xMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(yMirrorCurrentCylinder.GetOutput());
            tubes.AddInput(xyMirrorCurrentCylinder.GetOutput()); 
        }
        
        tubes.Update();
    }
    
    private void setTubesDieletric(double dieletric)
    {        
        vtkDoubleArray dieletricArray = new vtkDoubleArray();
        dieletricArray.SetNumberOfComponents(1);
        dieletricArray.SetNumberOfTuples(tubes.GetOutput().GetNumberOfCells());
        
         int nrOfCells = tubes.GetOutput().GetNumberOfCells();
         
        for (int i = 0; i < nrOfCells; i++)
            dieletricArray.SetTuple1(i, dieletric);
        
        tubes.GetOutput().GetCellData().SetScalars(dieletricArray);        
        tubes.Update();  
    }
    
    private void setCylinderDieletric(double dieletric)
    {
        vtkDoubleArray dieletricArray = new vtkDoubleArray();
        dieletricArray.SetNumberOfComponents(1);
        dieletricArray.SetNumberOfTuples(cylinder.GetOutput().GetNumberOfCells());
        
        int nrOfCells = cylinder.GetOutput().GetNumberOfCells();
         
        for (int i = 0; i < nrOfCells; i++)
            dieletricArray.SetTuple1(i, dieletric);
        
        cylinder.GetOutput().GetCellData().SetScalars(dieletricArray);        
        cylinder.Update();  
    }
    
    private void appendTubesWithCylinder()
    {
        device = new vtkAppendPolyData();
        device.AddInputConnection(cylinder.GetOutputPort());
        device.AddInputConnection(tubes.GetOutputPort());
        device.Update();
    }
    
    private void setDeviceScalar()
    {
        vtkDoubleArray color = new vtkDoubleArray();
        color.SetNumberOfComponents(1);
        int nrOfTuplesOfCylinder = cylinder.GetOutput().GetNumberOfCells();
        int nrOfTuplesOfTubes = tubes.GetOutput().GetNumberOfCells();
        color.SetNumberOfTuples(nrOfTuplesOfCylinder + nrOfTuplesOfTubes);         
        
        vtkDataArray cylinderDataArray = cylinder.GetOutput().GetCellData().GetScalars();
        
        //int nrCells = nrOfTuplesOfCylinder + nrOfTuplesOfTubes;
        
        for (int i = 0; i < nrOfTuplesOfCylinder; i++)
            color.SetTuple1(i, cylinderDataArray.GetTuple1(i));
        
        vtkDataArray tubesDataArray = tubes.GetOutput().GetCellData().GetScalars();
        
        for (int i = nrOfTuplesOfCylinder; i < (nrOfTuplesOfCylinder + nrOfTuplesOfTubes); i++)
            color.SetTuple1(i, tubesDataArray.GetTuple1(i));
        
        device.GetOutput().GetCellData().SetScalars(color);        
        //cylinder.Update();  
    }
    
    @Override
    public vtkPolyData getPolyData()
    {
        return device.GetOutput();
    }
}
